---
title: "並發與異步模型"
description: "學習 Rust 的並發程式設計、異步模型和多執行緒安全，對比 JavaScript 的事件循環機制"
---

# 並發與異步模型

## 📖 學習目標

理解 Rust 的並發程式設計模型，包括多執行緒、異步程式設計和執行緒安全機制，對比 JavaScript 的單執行緒事件循環模型。

---

## 🎯 執行模型對比

### JavaScript 的事件循環

JavaScript 使用單執行緒事件循環模型：

<UniversalEditor title="JavaScript 事件循環" compare={true}>
```javascript !! js
// JavaScript 單執行緒事件循環
console.log("開始執行");

// 同步程式碼
const result = 1 + 2;
console.log("同步計算:", result);

// 異步程式碼 - 微任務
Promise.resolve().then(() => {
    console.log("微任務 1");
});

// 異步程式碼 - 宏任務
setTimeout(() => {
    console.log("宏任務 1");
}, 0);

// 更多微任務
Promise.resolve().then(() => {
    console.log("微任務 2");
});

console.log("結束執行");

// 輸出順序：
// 開始執行
// 同步計算: 3
// 結束執行
// 微任務 1
// 微任務 2
// 宏任務 1

// 異步函數
async function fetchData() {
    console.log("開始獲取資料");
    
    // 模擬網路請求
    const response = await new Promise(resolve => {
        setTimeout(() => {
            resolve({ data: "Hello from server" });
        }, 1000);
    });
    
    console.log("資料獲取完成:", response.data);
    return response.data;
}

// 調用異步函數
fetchData().then(data => {
    console.log("處理資料:", data);
});

console.log("繼續執行其他程式碼");

// 並發處理（實際上是並發，不是並行）
async function processItems(items) {
    const promises = items.map(async (item) => {
        // 模擬異步處理
        await new Promise(resolve => setTimeout(resolve, 100));
        return `processed_${item}`;
    });
    
    const results = await Promise.all(promises);
    console.log("所有項目處理完成:", results);
}

processItems([1, 2, 3, 4, 5]);
```
</UniversalEditor>

雖然 JavaScript 本身是單執行緒的，但可以透過 **Web Workers** 實現多執行緒並發，將耗時的計算任務放到後台執行緒執行，避免阻塞主執行緒。這類似於 Rust 的多執行緒，但 Web Workers 之間不能直接共享記憶體，需要透過訊息傳遞進行通訊。

### Rust 的多執行緒模型

Rust 支援真正的多執行緒並行執行：

<UniversalEditor title="Rust 多執行緒" compare={true}>
```rust !! rs
use std::thread;
use std::time::Duration;

fn main() {
    println!("開始執行");
    
    // 同步程式碼
    let result = 1 + 2;
    println!("同步計算: {}", result);
    
    // 建立執行緒
    let handle = thread::spawn(|| {
        println!("執行緒 1 開始執行");
        thread::sleep(Duration::from_millis(100));
        println!("執行緒 1 執行完成");
    });
    
    // 主執行緒繼續執行
    println!("主執行緒繼續執行");
    
    // 等待執行緒完成
    handle.join().unwrap();
    println!("所有執行緒執行完成");
}

// 多執行緒資料處理
fn process_items_parallel(items: Vec<i32>) {
    let handles: Vec<_> = items.into_iter().map(|item| {
        thread::spawn(move || {
            // 模擬處理時間
            thread::sleep(Duration::from_millis(100));
            format!("processed_{}", item)
        })
    }).collect();
    
    // 收集所有執行緒的結果
    let results: Vec<String> = handles.into_iter()
        .map(|handle| handle.join().unwrap())
        .collect();
    
    println!("所有項目處理完成: {:?}", results);
}

// 使用執行緒池
use std::sync::mpsc;

fn main() {
    let (tx, rx) = mpsc::channel();
    
    // 發送執行緒
    thread::spawn(move || {
        let messages = vec![
            String::from("訊息 1"),
            String::from("訊息 2"),
            String::from("訊息 3"),
        ];
        
        for msg in messages {
            tx.send(msg).unwrap();
            thread::sleep(Duration::from_millis(100));
        }
    });
    
    // 接收執行緒
    for received in rx {
        println!("收到: {}", received);
    }
}
```
</UniversalEditor>

### 執行模型差異

1. **單執行緒 vs 多執行緒**: JavaScript 單執行緒事件循環，Rust 支援多執行緒並行
2. **並發 vs 並行**: JavaScript 並發非並行，Rust 可以真正並行
3. **記憶體安全**: JavaScript 執行時檢查，Rust 編譯時保證執行緒安全
4. **效能**: JavaScript 受單執行緒限制，Rust 可以充分利用多核心

---

## 🔒 執行緒安全與所有權

### 共享狀態管理

<UniversalEditor title="執行緒安全" compare={true}>
```rust !! rs
use std::sync::{Arc, Mutex};
use std::thread;

// 執行緒安全的計數器
struct SafeCounter {
    count: Mutex<i32>,
}

impl SafeCounter {
    fn new() -> Self {
        SafeCounter {
            count: Mutex::new(0),
        }
    }
    
    fn increment(&self) {
        let mut count = self.count.lock().unwrap();
        *count += 1;
    }
    
    fn get_count(&self) -> i32 {
        *self.count.lock().unwrap()
    }
}

fn main() {
    let counter = Arc::new(SafeCounter::new());
    let mut handles = vec![];
    
    // 建立多個執行緒同時增加計數器
    for _ in 0..10 {
        let counter = Arc::clone(&counter);
        let handle = thread::spawn(move || {
            for _ in 0..100 {
                counter.increment();
            }
        });
        handles.push(handle);
    }
    
    // 等待所有執行緒完成
    for handle in handles {
        handle.join().unwrap();
    }
    
    println!("最終計數: {}", counter.get_count()); // 應該是 1000
}

// 使用 RwLock 進行讀寫分離
use std::sync::RwLock;

struct DataStore {
    data: RwLock<Vec<String>>,
}

impl DataStore {
    fn new() -> Self {
        DataStore {
            data: RwLock::new(Vec::new()),
        }
    }
    
    fn write(&self, item: String) {
        let mut data = self.data.write().unwrap();
        data.push(item);
    }
    
    fn read(&self) -> Vec<String> {
        let data = self.data.read().unwrap();
        data.clone()
    }
}

fn main() {
    let store = Arc::new(DataStore::new());
    let mut handles = vec![];
    
    // 寫入執行緒
    for i in 0..5 {
        let store = Arc::clone(&store);
        let handle = thread::spawn(move || {
            store.write(format!("資料 {}", i));
        });
        handles.push(handle);
    }
    
    // 讀取執行緒
    for _ in 0..3 {
        let store = Arc::clone(&store);
        let handle = thread::spawn(move || {
            let data = store.read();
            println!("讀取到資料: {:?}", data);
        });
        handles.push(handle);
    }
    
    for handle in handles {
        handle.join().unwrap();
    }
}
```
</UniversalEditor>

---

## ⚡ 異步程式設計

### Rust 的異步程式設計

<UniversalEditor title="Rust 異步程式設計" compare={true}>
```rust !! rs
use tokio;
use std::time::Duration;

// 異步函數
async fn fetch_data() -> String {
    println!("開始獲取資料");
    
    // 模擬網路請求
    tokio::time::sleep(Duration::from_secs(1)).await;
    
    println!("資料獲取完成");
    String::from("Hello from server")
}

// 異步主函數
#[tokio::main]
async fn main() {
    println!("開始執行");
    
    // 調用異步函數
    let data = fetch_data().await;
    println!("處理資料: {}", data);
    
    println!("繼續執行其他程式碼");
}

// 並發異步任務
async fn process_items_async(items: Vec<i32>) -> Vec<String> {
    let mut handles = vec![];
    
    for item in items {
        let handle = tokio::spawn(async move {
            // 模擬異步處理
            tokio::time::sleep(Duration::from_millis(100)).await;
            format!("processed_{}", item)
        });
        handles.push(handle);
    }
    
    // 等待所有任務完成
    let mut results = vec![];
    for handle in handles {
        let result = handle.await.unwrap();
        results.push(result);
    }
    
    results
}

#[tokio::main]
async fn main() {
    let items = vec![1, 2, 3, 4, 5];
    let results = process_items_async(items).await;
    println!("所有項目處理完成: {:?}", results);
}

// 異步通道
use tokio::sync::mpsc;

async fn async_channel_example() {
    let (tx, mut rx) = mpsc::channel(100);
    
    // 發送任務
    let producer = tokio::spawn(async move {
        for i in 0..10 {
            tx.send(format!("訊息 {}", i)).await.unwrap();
            tokio::time::sleep(Duration::from_millis(100)).await;
        }
    });
    
    // 接收任務
    let consumer = tokio::spawn(async move {
        while let Some(message) = rx.recv().await {
            println!("收到: {}", message);
        }
    });
    
    // 等待兩個任務完成
    let _ = tokio::join!(producer, consumer);
}

#[tokio::main]
async fn main() {
    async_channel_example().await;
}
```
</UniversalEditor>

### 異步與多執行緒對比

<UniversalEditor title="異步 vs 多執行緒" compare={true}>
```rust !! rs
use std::time::Duration;
use tokio;

// 多執行緒版本 - 適合 CPU 密集型任務
fn cpu_intensive_task() -> i32 {
    // 模擬 CPU 密集型計算
    let mut result = 0;
    for i in 0..1_000_000 {
        result += i;
    }
    result
}

fn multi_threaded_example() {
    let start = std::time::Instant::now();
    
    let handles: Vec<_> = (0..4).map(|_| {
        std::thread::spawn(|| {
            cpu_intensive_task()
        })
    }).collect();
    
    let results: Vec<i32> = handles.into_iter()
        .map(|handle| handle.join().unwrap())
        .collect();
    
    let duration = start.elapsed();
    println!("多執行緒耗時: {:?}, 結果: {:?}", duration, results);
}

// 異步版本 - 適合 I/O 密集型任務
async fn io_intensive_task() -> String {
    // 模擬 I/O 操作
    tokio::time::sleep(Duration::from_millis(100)).await;
    String::from("I/O 任務完成")
}

async fn async_example() {
    let start = std::time::Instant::now();
    
    let handles: Vec<_> = (0..100).map(|_| {
        tokio::spawn(async {
            io_intensive_task().await
        })
    }).collect();
    
    let results: Vec<String> = futures::future::join_all(handles).await
        .into_iter()
        .map(|r| r.unwrap())
        .collect();
    
    let duration = start.elapsed();
    println!("異步耗時: {:?}, 處理了 {} 個任務", duration, results.len());
}

#[tokio::main]
async fn main() {
    // 比較兩種方法
    multi_threaded_example();
    async_example().await;
}
```
</UniversalEditor>

---

## 🎯 並發模式對比

### JavaScript 的並發模式

<UniversalEditor title="JavaScript 並發模式" compare={true}>
```javascript !! js
// JavaScript 的並發模式
class DataStore {
    constructor() {
        this.data = [];
        this.promise = Promise.resolve();
    }
    
    // 使用 Promise 鏈確保順序執行
    async write(item) {
        this.promise = this.promise.then(async () => {
            await new Promise(resolve => setTimeout(resolve, 100));
            this.data.push(item);
            console.log(`寫入: ${item}`);
        });
        return this.promise;
    }
    
    async read() {
        await this.promise;
        return [...this.data];
    }
}

// 使用範例
async function javascript_concurrency() {
    const store = new DataStore();
    
    // 並發寫入
    const writePromises = [];
    for (let i = 0; i < 5; i++) {
        writePromises.push(store.write(`資料 ${i}`));
    }
    
    // 等待所有寫入完成
    await Promise.all(writePromises);
    
    // 讀取資料
    const data = await store.read();
    console.log("讀取到資料:", data);
}

// Worker 執行緒（類似 Rust 的多執行緒）
if (typeof Worker !== 'undefined') {
    const worker = new Worker(`
        self.onmessage = function(e) {
            const result = e.data * 2;
            self.postMessage(result);
        };
    `);
    
    worker.onmessage = function(e) {
        console.log("Worker 計算結果:", e.data);
    };
    
    worker.postMessage(42);
}

javascript_concurrency();
```
</UniversalEditor>

### Rust 的並發模式

<UniversalEditor title="Rust 並發模式" compare={true}>
```rust !! rs
use std::sync::{Arc, Mutex};
use tokio::sync::RwLock;

// 執行緒安全的異步資料儲存
struct AsyncDataStore {
    data: Arc<RwLock<Vec<String>>>,
}

impl AsyncDataStore {
    fn new() -> Self {
        AsyncDataStore {
            data: Arc::new(RwLock::new(Vec::new())),
        }
    }
    
    async fn write(&self, item: String) {
        let mut data = self.data.write().await;
        tokio::time::sleep(tokio::time::Duration::from_millis(100)).await;
        data.push(item);
        println!("寫入: {}", item);
    }
    
    async fn read(&self) -> Vec<String> {
        let data = self.data.read().await;
        data.clone()
    }
}

#[tokio::main]
async fn rust_concurrency() {
    let store = Arc::new(AsyncDataStore::new());
    
    // 並發寫入
    let mut write_handles = vec![];
    for i in 0..5 {
        let store = Arc::clone(&store);
        let handle = tokio::spawn(async move {
            store.write(format!("資料 {}", i)).await;
        });
        write_handles.push(handle);
    }
    
    // 等待所有寫入完成
    for handle in write_handles {
        handle.await.unwrap();
    }
    
    // 讀取資料
    let data = store.read().await;
    println!("讀取到資料: {:?}", data);
}

// 使用 rayon 進行並行計算
use rayon::prelude::*;

fn parallel_computation() {
    let numbers: Vec<i32> = (0..1_000_000).collect();
    
    let start = std::time::Instant::now();
    
    // 並行計算
    let sum: i64 = numbers.par_iter()
        .map(|&x| x as i64)
        .sum();
    
    let duration = start.elapsed();
    println!("並行計算耗時: {:?}, 結果: {}", duration, sum);
}

fn main() {
    // 執行異步並發範例
    rust_concurrency();
    
    // 執行並行計算範例
    parallel_computation();
}
```
</UniversalEditor>

---

## 🎯 練習題

### 練習 1: 執行緒安全計數器

建立一個執行緒安全的計數器，支援多個執行緒同時增加計數：

<details>
<summary>查看答案</summary>

```rust
use std::sync::{Arc, Mutex};
use std::thread;

struct Counter {
    count: Mutex<i32>,
}

impl Counter {
    fn new() -> Self {
        Counter {
            count: Mutex::new(0),
        }
    }
    
    fn increment(&self) {
        let mut count = self.count.lock().unwrap();
        *count += 1;
    }
    
    fn get_count(&self) -> i32 {
        *self.count.lock().unwrap()
    }
}

fn main() {
    let counter = Arc::new(Counter::new());
    let mut handles = vec![];
    
    for _ in 0..10 {
        let counter = Arc::clone(&counter);
        let handle = thread::spawn(move || {
            for _ in 0..100 {
                counter.increment();
            }
        });
        handles.push(handle);
    }
    
    for handle in handles {
        handle.join().unwrap();
    }
    
    println!("最終計數: {}", counter.get_count()); // 應該是 1000
}
```

</details>

### 練習 2: 異步任務處理

建立一個異步函數，並發處理多個任務並收集結果：

<details>
<summary>查看答案</summary>

```rust
use tokio;
use std::time::Duration;

async fn process_task(id: i32) -> String {
    tokio::time::sleep(Duration::from_millis(100)).await;
    format!("任務 {} 完成", id)
}

async fn process_all_tasks() -> Vec<String> {
    let mut handles = vec![];
    
    for i in 0..10 {
        let handle = tokio::spawn(async move {
            process_task(i).await
        });
        handles.push(handle);
    }
    
    let mut results = vec![];
    for handle in handles {
        let result = handle.await.unwrap();
        results.push(result);
    }
    
    results
}

#[tokio::main]
async fn main() {
    let results = process_all_tasks().await;
    println!("所有任務完成: {:?}", results);
}
```

</details>

### 練習 3: 生產者消費者模式

實現一個生產者消費者模式，使用通道進行執行緒間通訊：

<details>
<summary>查看答案</summary>

```rust
use std::sync::mpsc;
use std::thread;
use std::time::Duration;

fn producer_consumer() {
    let (tx, rx) = mpsc::channel();
    
    // 生產者
    let producer = thread::spawn(move || {
        for i in 0..10 {
            tx.send(format!("產品 {}", i)).unwrap();
            thread::sleep(Duration::from_millis(100));
        }
    });
    
    // 消費者
    let consumer = thread::spawn(move || {
        for received in rx {
            println!("消費: {}", received);
        }
    });
    
    producer.join().unwrap();
    consumer.join().unwrap();
}

fn main() {
    producer_consumer();
}
```

</details>

---

## 📝 總結

在這一章中，我們學習了 Rust 的並發和異步程式設計：

1. **執行模型**: Rust 支援真正的多執行緒並行，JavaScript 是單執行緒事件循環
2. **執行緒安全**: Rust 透過所有權系統在編譯時保證執行緒安全
3. **異步程式設計**: Rust 的 async/await 語法與 JavaScript 類似
4. **並發模式**: 使用 Arc、Mutex、RwLock 等型別安全地共享狀態
5. **效能選擇**: 多執行緒適合 CPU 密集型，異步適合 I/O 密集型

### 關鍵要點

- Rust 的所有權系統確保執行緒安全
- 異步程式設計提供高性能的 I/O 處理
- 選擇合適的並發模型很重要
- 編譯時檢查避免執行時錯誤

### 下一步學習

在下一章中，我們將學習 Rust 的型別系統和特徵（Traits），了解如何建構可複用的抽象。

---

**繼續學習**: [型別系統與特徵](./module-05-type-system-traits)